﻿namespace Youtube_HD.Services
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;

    /// <summary>
    /// The http channel.
    /// </summary>
    public class HttpChannel : IHttpChannel
    {
        /// <summary>
        /// The regex name value pair.
        /// </summary>
        private static readonly Regex s_RegexNameValuePair = new Regex(
                                        @"(?<key>\w+)\s*=\s*((?<quote>\"")(?<value>[^\""]*)(\k<quote>)|(?<value>[^,]*))((,\s*)?)",
                                       RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.Singleline | RegexOptions.IgnoreCase);

        public HttpChannel()
        {

        }
        public static string GetQueryString(IDictionary<string, string> query)
        {
            string ret;
            if (query == null)
            {
                ret = string.Empty;
            }
            else
            {
                string queryString = query.Aggregate(
                    string.Empty,
                    (current, pair) => current + (Uri.EscapeDataString(pair.Key) + "=" + (pair.Value == null ? "" : Uri.EscapeDataString(pair.Value)) + "&"));
                queryString = string.Concat("?", queryString);
                ret = queryString.Trim('&');
            }

            return ret;
        }
        public async Task<string> GetDataYoutubeAsync(string urlParams)
        {
            string returnData = string.Empty;
            try
            {
                
                var request = (HttpWebRequest)WebRequest.Create(urlParams);
                request.Headers["Cache-Control"] = "no-cache";
                request.Headers["Pragma"] = "no-cache";
                HttpWebResponse response = await _GetResponseAsync(request);
                using (var sr = new StreamReader(response.GetResponseStream()))
                {
                    returnData = sr.ReadToEnd();
                }
            }
            catch (Exception)
            {
            }

            return returnData;
        }

        /// <summary>
        /// The get local path and query.
        /// </summary>
        /// <param name="uri">
        /// The uri.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string s_GetLocalPathAndQuery(Uri uri)
        {
            return uri.LocalPath + uri.Query;
        }

        /// <summary>
        /// The build parameter dictionary.
        /// </summary>
        /// <param name="header">
        /// The header.
        /// </param>
        /// <returns>
        /// The <see>
        ///         <cref>Dictionary</cref>
        ///     </see>
        ///     .
        /// </returns>
        private static Dictionary<string, string> s_BuildParameterDictionary(string header)
        {
            header = header.Substring(7);

            var matches = s_RegexNameValuePair.Matches(header);

            return matches.Cast<Match>().ToDictionary(m => m.Groups["key"].Value, m => m.Groups["value"].Value);
        }

        /// <summary>
        /// The generate new C nonce.
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private static string s_GenerateNewCNonce()
        {
            return Guid.NewGuid().ToString().Replace("-", string.Empty);
        }

        /// <summary>
        /// Data response from STB.
        /// </summary>
        /// <param name="request">
        /// The request.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private Task<HttpWebResponse> _GetResponseAsync(HttpWebRequest request)
        {
            var taskComplete = new TaskCompletionSource<HttpWebResponse>();
            request.BeginGetResponse(asyncResponse =>
            {
                try
                {
                    var responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
                    var someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
                    taskComplete.TrySetResult(someResponse);
                }
                catch (WebException webExc)
                {
                    var failedResponse = (HttpWebResponse)webExc.Response;
                    taskComplete.TrySetResult(failedResponse);
                }
                catch
                {
                }
            }, request);
            return taskComplete.Task;
        }
    }
}